fix(windows): align static Foundation autolinks - #5525
Conversation
Use the same static curl and compression archives in CMake builds that the package manifest already selects on Windows.
| "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend curl>") | ||
| if(WIN32) | ||
| target_compile_options(FoundationNetworking PRIVATE | ||
| "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend libcurl>" |
There was a problem hiding this comment.
I don't understand why the name changes here. It worked as curl there? That said the rename is likely better as the name is supposed to be the actual name on disk.
There was a problem hiding this comment.
The CMake path emitted an autolink for curl, which requests curl.lib, while the Windows static SDK packages the archive as libcurl.lib. A minimal FoundationNetworking executable therefore failed with LNK1104. The package manifest already names libcurl.lib, so this makes the CMake build match the working SwiftPM configuration.
There was a problem hiding this comment.
Right, but I mean, how has this been working? I suppose that this fix is for outside the CMake build as the curl target in CMake already points to the static library.
There was a problem hiding this comment.
Yeah, exactly. This change is for consumers of the installed static SDK that are outside the CMake target graph. In the in-tree build _CFURLSessionInterface links CURL::libcurl so final CMake targets resolve the imported target to the static archive and its link interface.
An external swiftc consumer cannot see that CMake target. It only sees the -public-autolink-library metadata embedded in the installed Swift module. On Windows those entries become /DEFAULTLIB:<name>.lib, so the names must match the SDK’s packaged files and the static curl dependencies must be listed explicitly. These directives are emitted only under NOT BUILD_SHARED_LIBS which is why the installed static-SDK reproducer exposed the problem
|
This does need a cross repo test to build the full static SDK |
|
@swift-ci please test Windows platform |
| "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend _CFURLSessionInterface>") | ||
| target_compile_options(FoundationNetworking PRIVATE | ||
| "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend curl>") | ||
| if(WIN32) |
There was a problem hiding this comment.
Elsewhere we use if(CMAKE_SYSTEM_NAME STREQUAL "Windows") to conditionalize when building for Windows. How does if(WIN32) behave differently (if at all) / should we use the other format used elsewhere instead?
There was a problem hiding this comment.
Updated in 0243902 to use CMAKE_SYSTEM_NAME STREQUAL "Windows", matching the condition style used elsewhere in this project.
There was a problem hiding this comment.
To clarify - I'm not 100% certain whether that is the correct syntax but rather I was asking why you chose WIN32 and whether there is a difference with the CMAKE_SYSTEM_NAME check
There was a problem hiding this comment.
Good question - I checked this directly with CMake 4.3.2. WIN32 was true for Windows, WindowsStore, WindowsPhone and WindowsCE while CMAKE_SYSTEM_NAME STREQUAL "Windows" selects only desktop Windows.
I originally used WIN32 as conventional shorthand, not because this change needed the broader Windows family. There is no benefit to that breadth here, so the narrower check matching the project's existing style is preferable. That is why I updated it.
| "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend brotlicommon>" | ||
| "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend brotlidec>") | ||
| else() | ||
| target_compile_options(FoundationNetworking PRIVATE |
There was a problem hiding this comment.
Why doesn't Linux need the extra auto linked libraries as well? The dependencies should be the same between Linux/Windows so I wouldn't expect anything to be windows specific here (except for maybe the name of the library if windows uses a different prefix for example)
There was a problem hiding this comment.
The Windows SDK builds and packages a static curl archive with zlib and Brotli enabled, but those archive dependencies are not encoded in its autolink metadata. Linux normally resolves the shared curl target and its dynamic dependencies; the existing BUILD_FULLY_STATIC path separately handles its static link additions. This Windows list also mirrors the existing Windows-only linker settings in Package.swift.
There was a problem hiding this comment.
Linux normally resolves the shared curl target and its dynamic dependencies
I don't think this is true - the static Linux SDK includes a libcurl.a, a libz.a, etc. The static Linux SDK should not be dynamically linking curl.
This Windows list also mirrors the existing Windows-only linker settings in Package.swift.
I don't think the Package.swift file is relevant here because it does not build static libraries - it dynamically links in the dependencies
There was a problem hiding this comment.
I don't think this is true - the static Linux SDK includes a libcurl.a, a libz.a, etc. The static Linux SDK should not be dynamically linking curl.
You are right about the underlying mechanism and my earlier comment conflated archive naming with linkage mode. On Unix, curl is the correct -l name for either libcurl.so or libcurl.a. The selected linkage mode determines which file is used. The relevant question here is which transitive archives the static curl build actually needs.
I checked the published Swift 6.3.3 Static Linux SDK and the latest main snapshot from 2026-07-11 for both x86_64 and aarch64. In all four configurations:
libcurl.areferences OpenSSL and zliblibcurl.ahas no unresolvedBrotli*symbols- The SDK ships
libcurl.a,libssl.a,libcrypto.a, and `libz.a - It does not ship
libbrotlicommon.aorlibbrotlidec.a swift-sdk.jsonandtoolset.jsoninject no dependency linker flags- A minimal
FoundationNetworkingexecutable links successfully
The generated autolink file contains -lcrypto, -lssl, -lcurl and -lz confirming that Linux's dependencies are supplied by the existing BUILD_FULLY_STATIC block. Brotli is absent because both published Linux curl archives were built without Brotli support.
Windows uses a different curl configuration: Schannel, zlib and Brotli. Its observed unresolved symbols are exactly the zlib and Brotli set. Therefore the platform-specific lists are intentional: Windows needs libcurl, zlibstatic, brotlicommon and brotlidec while Linux correctly retains curl plus the existing crypto, ssl and z autolinks.
I don't think the Package.swift file is relevant here because it does not build static libraries - it dynamically links in the dependencies
I agree that Package.swift does not establish the CMake or Linux behavior. Its narrower relevance is that its Windows _CFURLSessionInterface configuration defines CURL_STATICLIB and uses those same four Windows archive names.
The cross-repository full static SDK build @compnerd requested remains the final integration check. My @swift-ci request has not produced a visible run, so someone with CI access still needs to trigger it - I am happy to validate the result!
|
@swift-ci please test Windows platform |
|
Does the same problem exist with the libxml dependency for FoundationXML? |
Yes - the archive-name half of the same problem exists for FoundationXML. I reproduced it against the Swift 6.3.3 WindowsExperimental SDK. A static executable importing FoundationXML currently fails with Unlike curl the Windows libxml2 build has no companion static dependencies. Its build disables zlib, LZMA, iconv and ICU + the archive has no unresolved references to any of them. This agrees with Extended in fcd833c with the corresponding FoundationXML branch using Linux remains unchanged. I verified the Swift 6.3.3 release SDK and the 2026-07-11 development snapshot for x86_64 and aarch64: all four static executables link successfully with the existing I also checked every static public-autolink site in this repository: Foundation's existing archive names match the Windows SDK and FoundationNetworking plus FoundationXML are the two platform-specific dependency-name cases. The FoundationXML change is a separate commit - if you'd rather keep this PR scoped to networking, I'm happy to peel it off into an immediate follow-up! |
|
cc @compnerd - this extends the same archive-name fix to FoundationXML so the full static SDK build you requested will validate both in one run! |
| "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend xml2>") | ||
| if(CMAKE_SYSTEM_NAME STREQUAL "Windows") | ||
| target_compile_options(FoundationXML PRIVATE | ||
| "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -public-autolink-library -Xfrontend libxml2s>") |
There was a problem hiding this comment.
I think that this might be xml2s and not libxml2s
There was a problem hiding this comment.
I rechecked the installed SDK and the emitted directive. Both the x86_64 and ARM64 slices of the pinned WindowsExperimental SDK contain libxml2s.lib. Neither contains xml2s.lib or xml2.lib
The autolink argument is literal on Windows apart from the .lib suffix. The previous xml2 entry emitted /DEFAULTLIB:xml2.lib while libxml2s emits /DEFAULTLIB:libxml2s.lib. With that directive the static XMLParser reproducer links and prints true. Package.swift also names libxml2s.lib for Windows although the packaged SDK and functional link test are the decisive checks.
Are you seeing xml2s.lib in a different build-tree or SDK artifact? Could you please point me to it? Thanks!
Summary
curlandxml2autolinks.Validation
curl.libandxml2.liblink failures.libcurl.libandlibxml2s.libdirectives and linked successfully.libxml2s.liband omitxml2.lib.Related reports are thebrowsercompany/swift-build#351 and thebrowsercompany/swift-build#352.